﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;
using System.Xml;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


namespace ShevaEngineTools
{
    /// <summary>
    /// Typ knihovny - typicky pri zobrazovani formulare.
    /// </summary>
    public enum LibraryType { Textures, Models, Icons, Scenes };

    /// <summary>
    /// Hodnota, ktera je pozadovana jako navratova.
    /// </summary>
    public enum ReturnedValueType { Texture2D, Image, String };

    public partial class LibraryBrowserForm : Form
    {
        /// <summary>
        /// Struktura, ktera uchovava udaje o texture.
        /// </summary>
        [Serializable]
        struct TextureInfo
        {
            public string Size;

        }

        private bool libraryLoaded = false;
        /// <summary>
        /// Znaci, zda byla nahrana knihovna.
        /// </summary>
        public bool LibraryLoaded
        {
            get { return libraryLoaded; }
        }

        static int SmallIconsSize;
        static int MiddleIconsSize;
        static int LargeIconsSize;

        static string TexturesFolder;
        static string IconsFolder;
        static string ObjectsFolder;

        static string LibraryFileName;

        /// <summary>
        /// Momentalne nastavena velikost zobrazovanych ikon.
        /// </summary>
        public static string LibraryBrowserIconSize;

        /// <summary>
        /// Znaci, zda je mozne prepinat zobrazovany obsah.
        /// </summary>
        bool allowSwitchContent = false;
        
        /// <summary>
        /// Tabulka s polozkami pro ListView (s texturami, ikonami, atd.).
        /// </summary>
        Dictionary<string, ListViewItem[]> allListViewItemsDict;

        /// <summary>
        /// Tabulka s hlavickami ListView pro kazdy typ zobrazeni.
        /// </summary>
        Dictionary<string, ColumnHeader[]> allListViewColumnsDict;

        /// <summary>
        /// Tabulka se vsemi vygenerovanymi obrazky. Slouzi k serializaci.
        /// </summary>
        Dictionary<string, Image[]> allImagesDict;

        /// <summary>
        /// Tabulka s udaji o texturach, jejichz zmenseniny jsou ulozeny v Image[] poli.
        /// </summary>
        Dictionary<int, TextureInfo> allTexturesInfoDict;

        /// <summary>
        /// Knihovna, ktera je akorat zobrazovana.
        /// </summary>
        LibraryType currentBrowsing;

        /// <summary>
        /// Objekt, ktery vratil prohlizec.
        /// </summary>
        object browserReturnedObject = null;

        /// <summary>
        /// Hodnota, ktera je pozadovana jako navratova.
        /// </summary>
        ReturnedValueType? returnedValueType = ReturnedValueType.Texture2D;

        /// <summary>
        /// Docasne ulozene prazdne ikony, aby se nemusely ukladat pri kazdem pruchodu.
        /// </summary>
        Image smallNullIcon;
        Image middleNullIcon;
        Image largeNullIcon;
        
        /// <summary>
        /// Adresar, odkud se spousti EXE soubor.
        /// </summary>
        string executingDir;

        /// <summary>
        /// Delegat na metodu, ktera vytvari ImageListy.
        /// </summary>
        private delegate void CreateImageListD();

        private bool libraryCreatingRunning = false;
        /// <summary>
        /// Znaci, zda bezi metoda pro vytvareni ImageListu.
        /// </summary>
        public bool LibraryCreatingRunning
        {
            get { return libraryCreatingRunning; }
            set { libraryCreatingRunning = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        private readonly object sync = new object();

        /// <summary>
        /// Udalost, ktera se vyvola pri dokonceni vytvareni polozek ListView pro LibraryBrowser.
        /// </summary>
        public event AsyncCompletedEventHandler OnCreateLibraryCompleted;        


        #region ---UDALOSTI---

        /// <summary>
        /// Vyvola se pri kliknuti na polozku v kontextovem menu hlavniho ListView.
        /// </summary>
        public event EventHandler OnContextMenuClickEvent = null;

        /// <summary>
        /// Vyvola se pri kliknuti na polozku v ListView.
        /// </summary>
        public event EventHandler OnSelectedIndexChanged = null;

        #endregion

        #region ---KONSTRUKTORY---

        public LibraryBrowserForm(int smallIconsSize, int middleIconsSize, int largeIconsSize, string texturesFolder, string iconsFolder, string objectsFolder,
            string libraryFileName, string libraryBrowserIconSize)
            :this()
        {
            executingDir = System.Reflection.Assembly.GetExecutingAssembly().Location;
            executingDir = Path.GetDirectoryName(executingDir) + "\\";

            allListViewColumnsDict = new Dictionary<string, ColumnHeader[]>();
            allListViewItemsDict = new Dictionary<string, ListViewItem[]>();
            allImagesDict = new Dictionary<string, Image[]>();
            allTexturesInfoDict = new Dictionary<int, TextureInfo>();

            UpdateValues(smallIconsSize, middleIconsSize, largeIconsSize, texturesFolder, iconsFolder, objectsFolder, libraryFileName, libraryBrowserIconSize);
            
        }

        public LibraryBrowserForm()
        {
            InitializeComponent();

            foreach (string libraryType in Enum.GetNames(typeof(LibraryType)))
                contentSelector_ComboBox.Items.Add(libraryType);
        }

        #endregion

        /// <summary>
        /// Aktualizuje hodnoty z globalniho nastaveni.
        /// </summary>
        /// <param name="SmallIconsSize"></param>
        /// <param name="MiddleIconsSize"></param>
        /// <param name="LargeIconsSize"></param>
        /// <param name="TexturesFolder"></param>
        /// <param name="IconsFolder"></param>
        /// <param name="ObjectsFolder"></param>
        /// <param name="LibraryFileName"></param>
        /// <param name="libraryBrowserIconSize"></param>
        public static void UpdateValues(int smallIconsSize, int middleIconsSize, int largeIconsSize, string texturesFolder, string iconsFolder, string objectsFolder,
            string libraryFileName, string libraryBrowserIconSize)
        {
            SmallIconsSize = smallIconsSize;
            MiddleIconsSize = middleIconsSize;
            LargeIconsSize = largeIconsSize;
            TexturesFolder = texturesFolder;
            IconsFolder = iconsFolder;
            ObjectsFolder = objectsFolder;
            LibraryFileName = libraryFileName;
            LibraryBrowserIconSize = libraryBrowserIconSize;
        }


        #region Tvorba polozek

        /// <summary>
        /// Vytvori ImageListy a polozky pro ListView na pozadi.
        /// </summary>
        public void GenerateLibraryAsync()
        {
            CreateImageListD worker = new CreateImageListD(CreateLibrary);
            AsyncCallback completedCallback = new AsyncCallback(CreateLibraryTaskCompleted);

            lock (sync)
            {
                if (libraryCreatingRunning)
                    throw new Exception("Metoda na vytvoreni polozek pro LibraryBrowser stale bezi!");

                AsyncOperation async = AsyncOperationManager.CreateOperation(null);
                worker.BeginInvoke(completedCallback, async);
                libraryCreatingRunning = true;
            }
        }

        /// <summary>
        /// Vyvola se pri dokonceni ulohy pro tvorbu polozek pro ListView.
        /// </summary>
        private void CreateLibraryTaskCompleted(IAsyncResult ar)
        {
            CreateImageListD worker = (CreateImageListD)((AsyncResult)ar).AsyncDelegate;
            AsyncOperation async = (AsyncOperation)ar.AsyncState;

            worker.EndInvoke(ar);

            lock (sync)
            {
                libraryCreatingRunning = false;
            }

            AsyncCompletedEventArgs completedArgs = new AsyncCompletedEventArgs(null, false, null);
            async.PostOperationCompleted(delegate(object e) { CreateLibraryCompleted((AsyncCompletedEventArgs)e); }, completedArgs);
        }

        /// <summary>
        /// Vyvola se po dokonceni tvorby polozek ListView pro LibraryBrowser.
        /// </summary>
        /// <param name="e"></param>
        private void CreateLibraryCompleted(AsyncCompletedEventArgs e)
        {
            Serialize();

            if (OnCreateLibraryCompleted != null)
                OnCreateLibraryCompleted.Invoke(this, e);
        }

        /// <summary>
        /// Vytvori ImageListy, polozky pro ListView a vsechny dalsi potrebne UI prvky pro LibraryBrowser.
        /// </summary>
        public void CreateLibrary()
        {/*
            #region Vytvoreni prazdne ikony

            Texture2D nullIconTexture = ShevaEngine.Core.ShevaEngine.Instance.Content.Load<Texture2D>(IconsFolder + "nullIcon");
            MemoryStream stream;

            // Mala.
            stream = new MemoryStream();
            nullIconTexture.SaveAsPng(stream, SmallIconsSize, SmallIconsSize);
            smallNullIcon = Image.FromStream(stream);
            stream.Close();

            // Stredni.
            stream = new MemoryStream();
            nullIconTexture.SaveAsPng(stream, MiddleIconsSize, MiddleIconsSize);
            middleNullIcon = Image.FromStream(stream);
            stream.Close();

            // Velka.
            stream = new MemoryStream();
            nullIconTexture.SaveAsPng(stream, LargeIconsSize, LargeIconsSize);
            largeNullIcon = Image.FromStream(stream);
            stream.Close();

            #endregion
            */
            #region Vytvoreni Images

            // Pocatecni promenne.
            allImagesDict = new Dictionary<string, Image[]>();
            Dictionary<string, Image[]> images = new Dictionary<string, Image[]>();
            string prefix;

            // Textury.
            prefix = TexturesFolder;
            string texturesCompiledDir = executingDir + "Content\\"+ TexturesFolder;
            //string texturesImagesDir = solutionDir + "LibraryContent\\" + Settings.Global.FilesAndFoldersGlobalSet.TEXTURES_FOLDER;
            images = CreateImageListsForFiles(texturesCompiledDir, prefix);
            AddImagesToGlobalTable(images, prefix);

            // Ikony.
            prefix = IconsFolder;
            string iconsCompiledDir = executingDir + "LibraryContent\\" + IconsFolder;
            //string iconsImagesDir = solutionDir + "LibraryContent\\" + Settings.Global.FilesAndFoldersGlobalSet.ICONS_FOLDER;
            images = CreateImageListsForFiles(iconsCompiledDir, prefix);
            AddImagesToGlobalTable(images, prefix);

            // Objekty.
            prefix = ObjectsFolder;
            string objectsCompiledDir = executingDir + "LibraryContent\\" + ObjectsFolder;
            //string iconsCompiledDir = executingDir + "LibraryContent\\" + Settings.Global.FilesAndFoldersGlobalSet.ICONS_FOLDER;
            images = CreateImagesListForObjects(objectsCompiledDir, iconsCompiledDir, prefix);
            AddImagesToGlobalTable(images, prefix);

            // Sceny.
            prefix = "Scenes/";
            images = new Dictionary<string, Image[]>();
            Image[] newImages = new Image[1];
            newImages[0] = smallNullIcon;
            images.Add("smallImages", newImages);
            newImages[0] = middleNullIcon;
            images.Add("middleImages", newImages);
            newImages[0] = largeNullIcon;
            images.Add("largeImages", newImages);
            AddImagesToGlobalTable(images, prefix);


            #endregion

            #region Vytvoreni ListView polozek

            allListViewItemsDict = new Dictionary<string, ListViewItem[]>();
            List<string> files;
            ListViewItem item;
            List<ListViewItem> items;
            ListViewItem.ListViewSubItem subItem = new ListViewItem.ListViewSubItem();
            List<ListViewItem.ListViewSubItem> subItems = new List<ListViewItem.ListViewSubItem>();

            allListViewColumnsDict = new Dictionary<string, ColumnHeader[]>();
            ColumnHeader columnHeader;
            List<ColumnHeader> columHeaders;


            #region Textury

            #region Hlavicky

            columHeaders = new List<ColumnHeader>();

            columnHeader = new ColumnHeader();
            columnHeader.Text = "Jméno";
            columHeaders.Add(columnHeader);

            columnHeader = new ColumnHeader();
            columnHeader.Text = "Rozlišení";
            columHeaders.Add(columnHeader);

            allListViewColumnsDict.Add("textures", columHeaders.ToArray());

            #endregion

            #region Polozky

            files = GetFileNamesFromDirectory(texturesCompiledDir);
            items = new List<ListViewItem>();
            foreach (string name in files)
            {
                item = new ListViewItem();
                item.Name = name;
                item.Text = name;
                item.ImageIndex = files.IndexOf(name);

                subItem = new ListViewItem.ListViewSubItem();
                subItem.Text = allTexturesInfoDict[item.ImageIndex].Size;
                item.SubItems.Add(subItem);

                items.Add(item);
            }
            allListViewItemsDict.Add("textures", items.ToArray());

            #endregion

            #endregion

            // Ikony.
            files = GetFileNamesFromDirectory(iconsCompiledDir);
            items = new List<ListViewItem>();
            foreach (string name in files)
            {
                item = new ListViewItem();
                item.Name = name;
                item.Text = name;
                item.ImageIndex = files.IndexOf(name);

                subItem = new ListViewItem.ListViewSubItem();

                items.Add(item);
            }
            allListViewItemsDict.Add("icons", items.ToArray());


            #region Objekty

            #region Hlavicky

            columHeaders = new List<ColumnHeader>();

            columnHeader = new ColumnHeader();
            columnHeader.Text = "Jméno";
            columHeaders.Add(columnHeader);

            allListViewColumnsDict.Add("models", columHeaders.ToArray());

            #endregion

            #region Polozky

            files = GetFileNamesFromDirectory(objectsCompiledDir);
            items = new List<ListViewItem>();
            foreach (string name in files)
            {
                item = new ListViewItem();
                item.Name = name;
                item.Text = name;
                item.ImageIndex = files.IndexOf(name);

                subItem = new ListViewItem.ListViewSubItem();

                items.Add(item);
            }
            allListViewItemsDict.Add("models", items.ToArray());

            #endregion

            #endregion

            #region Sceny

            #region Hlavicky

            columHeaders = new List<ColumnHeader>();

            columnHeader = new ColumnHeader();
            columnHeader.Text = "Jméno scény";
            columHeaders.Add(columnHeader);

            columnHeader = new ColumnHeader();
            columnHeader.Text = "Počet objektů";
            columHeaders.Add(columnHeader);

            allListViewColumnsDict.Add("scenes", columHeaders.ToArray());

            #endregion

            //#region Polozky

            //XmlDocument doc = Loaders.LoadScenesXmlDocument();
            //items = new List<ListViewItem>();
            //foreach (XmlElement element in doc.DocumentElement.ChildNodes)
            //{
            //    item = new ListViewItem();
            //    item.Name = element.Name;
            //    item.Text = element.Name;
            //    item.ImageIndex = 0;

            //    // Pocet objektu.
            //    XmlNodeList gameObjectsElements = element.GetElementsByTagName("GameObjects");
            //    int gameObjectsCount = 0;
            //    if (gameObjectsElements.Count == 1)
            //        gameObjectsCount = gameObjectsElements[0].ChildNodes.Count;
            //    subItem = new ListViewItem.ListViewSubItem();
            //    subItem.Text = gameObjectsCount.ToString();
            //    item.SubItems.Add(subItem);

            //    items.Add(item);
            //}

            //allListViewItemsDict.Add("scenes", items.ToArray());

            //#endregion

            #endregion

            #endregion

        }

        /// <summary>
        /// Prida vygenerovane obrazky do globalni tabulky, ktera je serializovana.
        /// </summary>
        /// <param name="images"></param>
        private void AddImagesToGlobalTable(Dictionary<string, Image[]> images, string prefix)
        {
            foreach (string key in images.Keys)
            {
                prefix = prefix.ToLower().Replace("/", "");

                string newKey = key.ToUpper();

                Image[] img = images[key];
                allImagesDict.Add(prefix + newKey, img);
            }
        }

        /// <summary>
        /// Vytvori 3 pole s Image (ve trech velikostech) pro soubory v urcitem adresari, za predpokladu, ze soubory stejneho jmena jsou obsazeny v adresarich
        /// compiled i resources. 
        /// </summary>
        /// <param name="compiledFolder">Adresar se zkompilovanymi texturami.</param>
        /// <param name="resourcesFolder">Adresar s obrazky.</param>
        /// <param name="contentFolder">Adresar, ze ktereho se budou nahravat soubory pro ContentManager (Settings.Global.FilesAndFoldersGlobalSet.TEXTURES_FOLDER).</param>
        /// <returns></returns>
        private Dictionary<string, Image[]> CreateImageListsForFiles(string compiledFolder, string contentFolder)
        {
            // Databaze obrazku.
            List<Image> smallImages = new List<Image>();
            List<Image> middleImages = new List<Image>();
            List<Image> largeImages = new List<Image>();

            #region  Nacist jmena souboru v knihovne a v solution

            List<string> texturesCompiledNames = GetFileNamesFromDirectory(compiledFolder);
            //List<string> fileImagesNames = GetFileNamesFromDirectory(resourcesFolder);

            #endregion

            #region Vytvorit ikony a priradit je k ImageListum

            foreach (string textureImage in texturesCompiledNames)
                if (texturesCompiledNames.Contains(textureImage) || compiledFolder == null)
                {
                    Texture2D tex = ShevaEngine.Core.ShevaEngine.Instance.Content.Load<Texture2D>(contentFolder + textureImage);
                    MemoryStream stream;

                    // Male ikony.
                    stream = new MemoryStream();
                    tex.SaveAsPng(stream, SmallIconsSize, SmallIconsSize);
                    Image img = Image.FromStream(stream);
                    smallImages.Add(Image.FromStream(stream));
                    stream.Close();

                    // Stredni ikony.
                    stream = new MemoryStream();
                    tex.SaveAsPng(stream, MiddleIconsSize, MiddleIconsSize);
                    middleImages.Add(Image.FromStream(stream));
                    stream.Close();

                    // Velke ikony.
                    stream = new MemoryStream();
                    tex.SaveAsPng(stream, LargeIconsSize, LargeIconsSize);
                    largeImages.Add(Image.FromStream(stream));
                    stream.Close();

                    // Ulozeni dat o texture.
                    if (contentFolder == "Textures/")
                    {
                        TextureInfo ti = new TextureInfo();
                        ti.Size = String.Format("{0} x {1}", new object[] { tex.Width, tex.Height });
                        allTexturesInfoDict.Add(largeImages.Count - 1, ti);
                    }

                }

            // Vytvorit navratovou promennou.
            Dictionary<string, Image[]> images = new Dictionary<string, Image[]>();
            images.Add("smallImages", smallImages.ToArray());
            images.Add("middleImages", middleImages.ToArray());
            images.Add("largeImages", largeImages.ToArray());

            #endregion

            return images;
        }

        /// <summary>
        /// Vytvori 3 pole s Image (ve trech velikostech) pro vsechny soubory v urcitem adresari.
        /// </summary>
        /// <param name="resourcesFolder">Adresar s obrazky.</param>
        /// <param name="contentFolder">Adresar, ze ktereho se budou nahravat soubory pro ContentManager (Settings.Global.FilesAndFoldersGlobalSet.TEXTURES_FOLDER).</param>
        /// <returns></returns>
        private Dictionary<string, Image[]> CreateImagesListForObjects(string resourcesFolder, string iconsFolder, string prefix)
        {
            // Databaze obrazku.
            List<Image> smallImages = new List<Image>();
            List<Image> middleImages = new List<Image>();
            List<Image> largeImages = new List<Image>();

            // Jmena souboru.
            List<string> filesCompiledNames = GetFileNamesFromDirectory(resourcesFolder);
            List<string> compiledIconsList = GetFileNamesFromDirectory(iconsFolder);

            foreach (string file in filesCompiledNames)
            {
                if (!compiledIconsList.Contains(file))
                {
                    smallImages.Add(smallNullIcon);
                    middleImages.Add(middleNullIcon);
                    largeImages.Add(largeNullIcon);
                }
                else
                {
                    Texture2D tex = ShevaEngine.Core.ShevaEngine.Instance.Content.Load<Texture2D>(iconsFolder + file);
                    MemoryStream stream;

                    // Male ikony.
                    stream = new MemoryStream();
                    tex.SaveAsPng(stream, SmallIconsSize, SmallIconsSize);
                    Image img = Image.FromStream(stream);
                    smallImages.Add(Image.FromStream(stream));
                    stream.Close();

                    // Stredni ikony.
                    stream = new MemoryStream();
                    tex.SaveAsPng(stream, MiddleIconsSize, MiddleIconsSize);
                    middleImages.Add(Image.FromStream(stream));
                    stream.Close();

                    // Velke ikony.
                    stream = new MemoryStream();
                    tex.SaveAsPng(stream, LargeIconsSize, LargeIconsSize);
                    largeImages.Add(Image.FromStream(stream));
                    stream.Close();
                }
            }

            // Vytvorit navratovou promennou.
            Dictionary<string, Image[]> images = new Dictionary<string, Image[]>();
            images.Add("smallImages", smallImages.ToArray());
            images.Add("middleImages", middleImages.ToArray());
            images.Add("largeImages", largeImages.ToArray());

            return images;

        }

        #endregion

        #region Udalosti hlavniho ListView

        /// <summary>
        /// Vyvola se po kliknuti na polozku v ListView.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void main_ListView_SelectedIndexChanged(object sender, EventArgs e)
        {
            ListView lv = (ListView)sender;
            if (lv.SelectedItems.Count == 0)
                return;

            string name = lv.SelectedItems[0].Text;

            CreateFullSizeImage(name);
        }

        /// <summary>
        /// Vytvori obrazek v plne velikosti, odpovidajici jmenu.
        /// </summary>
        /// <param name="name">Jmeno obrazku.</param>
        private void CreateFullSizeImage(string name)
        {
            Image finalImage = null;

            #region Zjisteni jmena adresare a typu objektu

            switch (currentBrowsing)
            {
                case LibraryType.Textures:
                    finalImage = GetFullSizeTextureImage(name);
                    break;

                case LibraryType.Icons:
                    finalImage = GetFullSizeTextureImage(name);
                    break;

                case LibraryType.Models:
                    break;

                case LibraryType.Scenes:
                    break;

                default:
                    throw new NotImplementedException();
            }

            #endregion

            main_PictureBox.Image = finalImage;
            if (finalImage != null)
                label1.Text = string.Format("Velikost: {0} x {1}", finalImage.Width, finalImage.Height);
            else
                label1.Text = "";

        }

        /// <summary>
        /// Nacte a vygeneruje Image objekt z obrazku v knihovne.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        private Image GetFullSizeTextureImage(string name)
        {
            Texture2D texture = GetFullSizeTexture(name);

            MemoryStream stream = new MemoryStream();
            texture.SaveAsPng(stream, texture.Width, texture.Height);
            Image img = Image.FromStream(stream);

            return img;
        }

        /// <summary>
        /// Nacte texturu z Contentu.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        private Texture2D GetFullSizeTexture(string name)
        {
            Texture2D texture = ShevaEngine.Core.ShevaEngine.Instance.Content.Load<Texture2D>(currentBrowsing.ToString().ToLower() + "/" + name);
            return texture;
        }

        #endregion

        #region Udalosti tlacitek

        void cancel_Button_Click(object sender, EventArgs e)
        {
            browserReturnedObject = null;
            Close();
        }

        void ok_Button_Click(object sender, EventArgs e)
        {
            if (returnedValueType == null)
                return;

            if (main_ListView.SelectedItems.Count == 0)
            {
                browserReturnedObject = null;
                Close();
                return;
            }

            string assetName = main_ListView.SelectedItems[0].Text;

            switch (returnedValueType)
            {
                case ReturnedValueType.String:
                    browserReturnedObject = assetName;
                    break;

                case ReturnedValueType.Texture2D:
                    browserReturnedObject = GetFullSizeTexture(assetName);
                    break;

                case ReturnedValueType.Image:
                    browserReturnedObject = GetFullSizeTextureImage(assetName);
                    break;

                default:
                    browserReturnedObject = null;
                    break;
            }

            Close();
        }

        #endregion

        #region Serializace

        /// <summary>
        /// Ulozi potrebne promenne na disk.
        /// </summary>
        public void Serialize()
        {
            BinaryFormatter bf = new BinaryFormatter();
            Stream fs = File.Open(LibraryFileName, FileMode.OpenOrCreate);

            bf.Serialize(fs, allListViewItemsDict);
            bf.Serialize(fs, allImagesDict);
            bf.Serialize(fs, GetObjectForSerializeColumnHeaders());
            bf.Serialize(fs, allTexturesInfoDict);

            fs.Close();
        }

        /// <summary>
        /// Nacte potrebne promenne z disku.
        /// </summary>
        public void Deserialize()
        {
            BinaryFormatter bf = new BinaryFormatter();
            Stream fs = File.Open(LibraryFileName, FileMode.OpenOrCreate);

            allListViewItemsDict = bf.Deserialize(fs) as Dictionary<string, ListViewItem[]>;
            allImagesDict = bf.Deserialize(fs) as Dictionary<string, Image[]>;
            allListViewColumnsDict = DeserializeColumnHeaders(bf.Deserialize(fs));// as Dictionary<string, ColumnHeader[]>;
            allTexturesInfoDict = bf.Deserialize(fs) as Dictionary<int, TextureInfo>;

            fs.Close();

            SetRightImageList();

            libraryLoaded = true;
        }

        /// <summary>
        /// Jelikoz typ "ColumnHeader" nelze serializovat, vytvori se pomocny objekt pro jeho serializaci.
        /// </summary>
        private object GetObjectForSerializeColumnHeaders()
        {
            Dictionary<string, List<string>> columnsHelper = new Dictionary<string, List<string>>();

            foreach (string name in allListViewColumnsDict.Keys)
            {
                List<string> columnHeaderText = new List<string>();

                foreach (ColumnHeader column in allListViewColumnsDict[name])
                    columnHeaderText.Add(column.Text);

                columnsHelper.Add(name, columnHeaderText);
            }

            return columnsHelper;
        }

        /// <summary>
        /// Jelikoz typ "ColumnHeader" nelze serializovat, vytvori se pomocny objekt pro jeho deserializaci.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private Dictionary<string,ColumnHeader[]> DeserializeColumnHeaders(object obj)
        {
            Dictionary<string, List<string>> columnsHelper = obj as Dictionary<string, List<string>>;
            Dictionary<string, ColumnHeader[]> columnHeaders = new Dictionary<string, ColumnHeader[]>();

            ColumnHeader columnHeader;

            foreach (string name in columnsHelper.Keys)
            {
                List<ColumnHeader> columns = new List<ColumnHeader>();

                foreach (string text in columnsHelper[name])
                {
                    columnHeader = new ColumnHeader();
                    columnHeader.Text = text;
                    columnHeader.Width = 100;
                    columns.Add(columnHeader);
                }

                columnHeaders.Add(name, columns.ToArray());
            }

            return columnHeaders;
        }

        #endregion

        /// <summary>
        /// Na zaklade retezce vrati typ knihovny.
        /// </summary>
        /// <param name="typeStr"></param>
        /// <returns></returns>
        public LibraryType GetLibraryTypeFromString(string typeStr)
        {
            foreach (LibraryType type in Enum.GetValues(typeof(LibraryType)))
                if (type.ToString() == typeStr)
                    return type;

            throw new Exception("Spatny typ");
        }

        /// <summary>
        /// Vrati jmena souboru (bez pripon) z urciteho adresare a seradi dle nazvu.
        /// </summary>
        /// <param name="directory"></param>
        /// <returns></returns>
        private List<string> GetFileNamesFromDirectory(string directory)
        {
            List<string> fileNames = new List<string>();

            string[] files = Directory.GetFiles(directory);

            foreach (string file in files)
                fileNames.Add(Path.GetFileNameWithoutExtension(file));
            fileNames.Sort();

            return fileNames;
        }

        /// <summary>
        /// Otevre prohlizec pouze pro prohlizeni.
        /// </summary>
        public void OpenLibraryBrowser()
        {
            SetBrowserFor(currentBrowsing.ToString());

            returnedValueType = null;
            allowSwitchContent = true;

            ShowFormDialog();

        }

        /// <summary>
        /// Zobrazi prohlizec knihovny pro urcity typ a vrati objekt, ktery je v prohlizeci zvolen.
        /// </summary>
        /// <param name="libraryType"></param>
        /// <returns></returns>
        public object GetContentByLibraryBrowser(LibraryType libraryType, ReturnedValueType? returnedValueType)
        {
            if (!libraryLoaded)
                Deserialize();
            
            allowSwitchContent = false;

            //Input.StrategyInput input = MainGame.Services.GetService(typeof(Input.StrategyInput)) as Input.StrategyInput;

            this.returnedValueType = returnedValueType;

            SetBrowserFor(libraryType.ToString());

            ShowFormDialog();

            return browserReturnedObject;
        }

        /// <summary>
        /// Vyvola se pri kliknuti na polozku v kontextovem menu hlavniho ListView.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mainLV_ContextMenuStrip_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem menu = (ToolStripMenuItem)sender;

            switch (menu.Name)
            {
                case "showSmallIcons_ContextMenu":
                    LibraryBrowserIconSize = "small";
                    break;

                case "showMiddleIcons_ContextMenu":
                    LibraryBrowserIconSize = "middle";
                    break;

                case "showLargeIcons_ContextMenu":
                    LibraryBrowserIconSize = "large";
                    break;

                case "showList_ContextMenu":
                    LibraryBrowserIconSize = "list";
                    break;

                case "showDetails_ContextMenu":
                    LibraryBrowserIconSize = "details";
                    break;
            }

            SetRightImageList();
        }

        /// <summary>
        /// Na zaklade zvolene velikosti zobrazovanych ikon nastavi spravne ImageListy.
        /// </summary>
        private void SetRightImageList()
        {
            switch (LibraryBrowserIconSize)
            {
                case "large":
                    main_ListView.LargeImageList = large_ImageList;
                    main_ListView.View = View.LargeIcon;
                    break;

                case "middle":
                    main_ListView.LargeImageList = middle_ImageList;
                    main_ListView.View = View.LargeIcon;
                    break;

                case "small":
                    main_ListView.SmallImageList = small_ImageList;
                    main_ListView.View = View.SmallIcon;
                    break;

                case "list":
                    main_ListView.SmallImageList = small_ImageList;
                    main_ListView.View = View.List;
                    break;

                case "details":
                    main_ListView.SmallImageList = null;
                    main_ListView.LargeImageList = null;
                    main_ListView.View = View.Details;
                    break;
            }
        }

        /// <summary>
        /// Vytvori nove ImageListy.
        /// </summary>
        private void CreateImageLists()
        {
            small_ImageList = new ImageList();
            small_ImageList.ImageSize = new Size(SmallIconsSize, SmallIconsSize);
            small_ImageList.ColorDepth = ColorDepth.Depth16Bit;

            middle_ImageList = new ImageList();
            middle_ImageList.ImageSize = new Size(MiddleIconsSize, MiddleIconsSize);
            middle_ImageList.ColorDepth = ColorDepth.Depth16Bit;

            large_ImageList = new ImageList();
            large_ImageList.ImageSize = new Size(LargeIconsSize, LargeIconsSize);
            large_ImageList.ColorDepth = ColorDepth.Depth16Bit;
        }


        /// <summary>
        /// Zobrazi formular formou dialogu.
        /// </summary>
        /// <returns></returns>
        public object ShowFormDialog()
        {
            contentSelector_ComboBox.Enabled = allowSwitchContent;
            ok_Button.Visible = !allowSwitchContent;

            if (libraryCreatingRunning)
            {
                MessageBox.Show("Knihovna se vytváří, forulář nebude zobrazen", "Chyba", MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
                return null;
            }

            DialogResult result = ShowDialog();
            if (result == DialogResult.OK)
                return browserReturnedObject;
            else
                return null;
        }


        /// <summary>
        /// Nastavi prohlizec pro prohlizeni urcite knihovny.
        /// </summary>
        /// <param name="name">Jmeno knihovny.</param>
        private void SetBrowserFor(string name)
        {
            currentBrowsing = (LibraryType)Enum.Parse(typeof(LibraryType), name);
            contentSelector_ComboBox.Text = name;

            name = name.ToLower();

            main_ListView.Items.Clear();
            main_ListView.Items.AddRange(allListViewItemsDict[name]);
            main_ListView.Columns.Clear();
            if (allListViewColumnsDict.ContainsKey(name))
                main_ListView.Columns.AddRange(allListViewColumnsDict[name]);

            CreateImageLists();

            small_ImageList.Images.AddRange(allImagesDict[name + "SmallImages"]);
            middle_ImageList.Images.AddRange(allImagesDict[name + "MiddleImages"]);
            large_ImageList.Images.AddRange(allImagesDict[name + "LargeImages"]);

            SetRightImageList();
        }
      
        private void main_PictureBox_Click(object sender, EventArgs e)
        {
            //TextureWindowForm texWinForm = new TextureWindowForm(main_PictureBox.Image, label1.Text.Remove(label1.Text.IndexOf(':')));
            //texWinForm.ShowDialog();
        }

        private void contentSelector_ComboBox_TextChanged(object sender, EventArgs e)
        {
            // Test na spravny text.
            List<string> possible = new List<string>();
            foreach(string name in Enum.GetNames(typeof(LibraryType)))
                possible.Add(name);

            if (possible.Contains(contentSelector_ComboBox.Text))
                SetBrowserFor(contentSelector_ComboBox.Text);
        }

    }
}
